﻿package com.hotel.BL;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.EntityName;
import com.Util;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.appengine.labs.repackaged.org.json.JSONException;

import data.General;
import data.Task;

public class TaskLogic extends AbstractBL {
	
	public TaskLogic(HttpServletRequest req,HttpServletResponse resp){
		this.req =req;
		this.resp = resp;
	}

	//test
	static int counter = 0;
	static List<Entity> normalEntities = new ArrayList<Entity>();
			
	public Map<String,Long> CountTask(long hotelId) throws JSONException
	{			
		long criticalSize = 0;
		long warningSize = 0;
		long normalSize = 0;
		
		long minW;
		long minC;
		HttpSession session = req.getSession(true);
		if(session.getAttribute("MinuteForWarning")!=null && session.getAttribute("MinuteForCritical")!=null){
			minW = (Long) session.getAttribute("MinuteForWarning");
			minC = (Long) session.getAttribute("MinuteForCritical");
		}else{
			GenericLogic gLogic = new GenericLogic(req,resp);
			General g = gLogic.GetGeneral(hotelId);
			minW = g.getMinuteForWarning();
			minC = g.getMinuteForCritical();
		}
		

		//TODO: check date for get critical/warning/normal
		Query q = new Query(EntityName.Task);
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterStatus = new FilterPredicate("status",FilterOperator.EQUAL,"Normal");
		Filter filterComplete = new FilterPredicate("isComplete",FilterOperator.EQUAL,false);
		Filter filterTrash = new FilterPredicate("isTrash",FilterOperator.EQUAL,false);
		Filter filter = CompositeFilterOperator.and(filterHotel,filterStatus,filterComplete,filterTrash);
		q.setFilter(filter);

		normalSize = GetList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults())).size();
		warningSize = CountTaskByStatus(hotelId,minW,minC);
		criticalSize = CountTaskByStatus(hotelId,minC,-1);

		Map<String,Long> obj = new HashMap<String,Long>();
		obj.put("C", criticalSize);
		obj.put("W", warningSize);
		obj.put("N", normalSize - warningSize - criticalSize);
		
		return obj;
	}
	private long CountTaskByStatus(long hotelId,long mins1,long mins2){
		GenericLogic gLogic = new GenericLogic(req,resp);
		Date d = gLogic.ServerDateTime(hotelId);
		
		Query q = new Query(EntityName.Task);
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterStatus = new FilterPredicate("status",FilterOperator.EQUAL,"Normal");
		Filter filterComplete = new FilterPredicate("isComplete",FilterOperator.EQUAL,false);
		Filter filterTrash = new FilterPredicate("isTrash",FilterOperator.EQUAL,false);
		Filter filterSetDue = new FilterPredicate("isSetDue",FilterOperator.EQUAL,true);
		Filter filterDue1 = new FilterPredicate("due",FilterOperator.LESS_THAN_OR_EQUAL,Util.addMins(d, mins1));
		Filter filter = CompositeFilterOperator.and(filterHotel,filterStatus,filterComplete,filterTrash,filterSetDue,filterDue1);
		if(mins2>0)
			filter = CompositeFilterOperator.and(filter,new FilterPredicate("due",FilterOperator.GREATER_THAN,Util.addMins(d, mins2)));
		q.setFilter(filter);

		return GetList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults())).size();
	}
	public Key CreateTask(long hotelId,String title)
	{
		Task task = new Task();
		task.setTaskTitle(title);
		return CreateTask(hotelId,task);
	}
	
	public Key CreateTask(long hotelId,String title,String roomName)
	{
		Task task = new Task();
		task.setTaskTitle(title);
		task.setRoomName(roomName);
		return CreateTask(hotelId,task);
	}
	
	public Key CreateTask(long hotelId,String title,Date due)
	{
		Task task = new Task();
		task.setTaskTitle(title);
		task.setDue(due);
		return CreateTask(hotelId,task);
	}
	
	public Key CreateTask(long hotelId,String title,String roomName,Date due)
	{
		Task task = new Task();
		task.setTaskTitle(title);
		task.setRoomName(roomName);
		task.setDue(due);
		return CreateTask(hotelId,task);
	}

	public Key CreateTask(long hotelId,Task task)
	{
		task.setHotelId(hotelId);
		task.setStatus("Normal");
		return datastore.put(task.getEntity());
	}

	public Boolean CloseTask(long taskId)
	{
		Key key = KeyFactory.createKey(EntityName.Task, taskId);
		try {
			Entity task = datastore.get(key);
			task.setProperty("isComplete", true);
			datastore.put(task);
			
		} catch (EntityNotFoundException e) {
			//e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public List<Task> GetFist10Task(long hotelId)
	{		
		Query q = new Query(EntityName.Task);
		
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterStatus = new FilterPredicate("status",FilterOperator.EQUAL,"Normal");
		Filter filterComplete = new FilterPredicate("isComplete",FilterOperator.EQUAL,false);
		Filter filterTrash = new FilterPredicate("isTrash",FilterOperator.EQUAL,false);

		Filter filter = CompositeFilterOperator.and(filterHotel, filterStatus,filterComplete,filterTrash);
		
		q.setFilter(filter).addSort("due");
		
		return GetList(datastore.prepare(q).asList(FetchOptions.Builder.withLimit(10)));
	}
	public List<Task> GetFistAllTask(long hotelId)
	{		
		Query q = new Query(EntityName.Task);
		
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterStatus = new FilterPredicate("status",FilterOperator.EQUAL,"Normal");
		Filter filterComplete = new FilterPredicate("isComplete",FilterOperator.EQUAL,false);

		Filter filter = CompositeFilterOperator.and(filterHotel,filterComplete, filterStatus);
		
		q.setFilter(filter)
		.addSort("due");
		
		return GetList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
	}
	public List<Task> GetList(List<Entity> entities)
	{
		List<Task> list = new ArrayList<Task>();
		for(Entity e : entities)
		{
			Task t = new Task();
			t.setEntity(e);
			list.add(t);
		}
		return list;
	}
	
	public Task AddTaskNote(String detail,long hotelId,Boolean isstar,String status,String tasktitle, String roomName) throws EntityNotFoundException{
		Task t = new Task();
		t.setDetail(detail);
	    t.setDue(new Date());
		t.setHotelId(hotelId);
		t.setStar(isstar);
		t.setStatus(status);
		t.setTaskTitle(tasktitle);
		t.setRoomName(roomName);
		t.setTrash(false);
		t.setComplete(false);
		t.setSetDue(false);
		Key k = datastore.put(t.getEntity());
		t.setId(k.getId());
		t.setKey(k);
		return t;
	}
	
	public Task AddTaskNote(String detail,long hotelId,Boolean isstar,String status,String tasktitle, String roomName,Date due) throws EntityNotFoundException{
		Task t = new Task();
		t.setDetail(detail);
	    t.setDue(due);
		t.setHotelId(hotelId);
		t.setStar(isstar);
		t.setStatus(status);
		t.setTaskTitle(tasktitle);
		t.setRoomName(roomName);
		t.setTrash(false);
		t.setComplete(false);
		t.setSetDue(true);
		Key k = datastore.put(t.getEntity());
		t.setId(k.getId());
		t.setKey(k);
		return t;
	}

	public Task EditCloseTask(long hotelId, long int_id, String status_task)
			throws EntityNotFoundException, ParseException {
		Task g = GetTaskNote(int_id);
		g.setStatus(status_task);
		Key k = datastore.put(g.getEntity());
		g.setId(k.getId());
		g.setKey(k);
		return g;
	}
	public Task EditIsStarTask(long hotelId, long int_id, Boolean isStar)
			throws EntityNotFoundException, ParseException {
		Task g = GetTaskNote(int_id);
		g.setStar(isStar);
		Key k = datastore.put(g.getEntity());
		g.setId(k.getId());
		g.setKey(k);
		return g;
	}
	public Task EditTitleTask(long hotelId, long int_id, String title)
			throws EntityNotFoundException, ParseException {
		Task g = GetTaskNote(int_id);
		g.setTaskTitle(title);
		Key k = datastore.put(g.getEntity());
		g.setId(k.getId());
		g.setKey(k);
		return g;
	}
	public Task EditDueTask(long hotelId, long int_id, Date due)
			throws EntityNotFoundException, ParseException {
		Task g = GetTaskNote(int_id);
		g.setDue(due);
		g.setSetDue(true);
		Key k = datastore.put(g.getEntity());
		g.setId(k.getId());
		g.setKey(k);
		return g;
	}
	public Task EditDetailTask(long hotelId, long int_id, String detail)
			throws EntityNotFoundException, ParseException {
		Task g = GetTaskNote(int_id);
		g.setDetail(detail);
		Key k = datastore.put(g.getEntity());
		g.setId(k.getId());
		g.setKey(k);
		return g;
	}
	public Task EditStatusTask(long hotelId, long int_id, String status, String delete)
			throws EntityNotFoundException, ParseException {
		Task g = GetTaskNote(int_id);
		if(delete.equals("checked")&&status.equals("Delete")){
			status ="Delete_Close";
		}
		g.setStatus(status);
		Key k = datastore.put(g.getEntity());
		g.setId(k.getId());
		g.setKey(k);
		return g;
	}
////Get
	public Task GetTaskNote(long hotelId ,long task_id)
	{	
		Key key = KeyFactory.createKey(EntityName.Task, task_id);
		try {
			Entity lang = datastore.get(key);
			Task c = new Task();
			c.setEntity(lang);
			return c;
		} catch (EntityNotFoundException e) {
			return null;
		}
	}
	public List<Task> GetListTask(List<Entity> entities)
	{
		List<Task> list = new ArrayList<Task>();
		for(Entity e : entities)
		{
			Task t = new Task();
			t.setEntity(e);
			list.add(t);
		}
		return list;
	}
	public Task GetTaskNote(long id) {
		Key key = KeyFactory.createKey(EntityName.Task, id);
		try {
			Entity lang = datastore.get(key);
			Task c = new Task();
			c.setEntity(lang);
			return c;
		} catch (EntityNotFoundException e) {
			return null;
		}
	}
	public Task GetIdTaskList(long hotelId ,long res_id)
	{		
		Query q = new Query(EntityName.Task);
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterStatus = new FilterPredicate("status",FilterOperator.EQUAL,"Normal");
		//Filter filterId = new FilterPredicate("id",FilterOperator.EQUAL,);
		Filter filter = CompositeFilterOperator.and(filterHotel, filterStatus);
		
		q.setFilter(filter)
		.addSort("due");
		Entity lang = datastore.prepare(q).asSingleEntity();
		Task c = new Task();
		c.setEntity(lang);
		return c;
	}

	public Task UpdateTask(Task t)
	{
		Key key = datastore.put(t.getEntity());
		t.setId(key.getId());
		t.setKey(key);
		return t;
	}
}
